package cn.com.twoke.game.client.ui;

import cn.com.twoke.game.client.GameClientManager;
import cn.com.twoke.game.client.cache.ClientCacheManager;
import cn.com.twoke.game.client.games.GameConfig;
import cn.com.twoke.game.client.games.GameManager;
import cn.com.twoke.game.client.utils.TextUtil;
import cn.com.twoke.game.common.entity.message.InviteJoinGameMessage;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

public class WindowUI extends BaseUI implements MouseListener {


    private static final Integer WIDTH = 800;
    private static final Integer HEIGHT = 600;
    private  Content content;


    public WindowUI() throws HeadlessException {
        super("主界面");
        Dimension dimension = new Dimension(WIDTH, HEIGHT);
        this.setSize(dimension);
        this.setMinimumSize(dimension);
        this.setMaximumSize(dimension);
        this.setResizable(false);

        content = new Content();
        this.add(content);
        // this.addWindowListener()
        this.setLocationRelativeTo(null);
        this.pack();
        this.addMouseListener(this);
    }

    public void open() {
        setTitle("主界面 - " + ClientCacheManager.INSTANCE.getUsername());
        setVisible(true);
    }


    // @Override
    // public JPanel initContent() {
    //     return content;
    // }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    private  GameConfig config;
    private List<String> selectedPlayerName;
    private String gameRoomId;

    @Override
    public void mouseReleased(MouseEvent e) {
        Point point = e.getPoint();
        point.y = point.y - 30;
        if (content.state == Content.State.SELECT_GAME) {
            Content.forEach((row, col, rect, config) -> {
                if (rect.contains(point)) {
                    this.config = config;
                    this.setTitle("用户：【" + ClientCacheManager.INSTANCE.getUsername() + "】 " + this.config.getTitle() + " - 选择玩家");
                    selectedPlayerName = new ArrayList<>();
                    selectedPlayerName.add(0, ClientCacheManager.INSTANCE.getUsername());
                    gameRoomId = UUID.randomUUID().toString();
                    content.setRoomMasterId(ClientCacheManager.INSTANCE.getUsername());
                    content.selectPlayer(config, selectedPlayerName);
                    content.repaint();
                }
            });
        }
        if (content.state == Content.State.SELECT_PLAYER) {
            if (null != content.addPlayerBtn && content.addPlayerBtn.contains(point)) {
                // 显示带有复选框的对话框
                List<String> userIds = Arrays.asList(ClientCacheManager.INSTANCE.getUserIds())
                        .stream().filter(item -> !item.equals(ClientCacheManager.INSTANCE.getUsername()))
                        .collect(Collectors.toList());
                if (userIds.size() == 0) {
                    JOptionPane.showMessageDialog(this, "没有可选在线用户");
                    return;
                }
                JPanel panel = new JPanel();
                panel.setLayout(new GridLayout(userIds.size(), 1));
                JCheckBox[] checkBox = new JCheckBox[userIds.size()];
                ActionListener checkBoxListener = new ActionListener() {
                    int selectedCount = 0;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JCheckBox source = (JCheckBox) e.getSource();
                        if (source.isSelected()) {
                            selectedCount++;
                        } else {
                            selectedCount--;
                        }
                        if (selectedCount >= config.getMaxPlayers() - 1) {
                            // 达到最大选择数量，禁用未选中的复选框
                            for (JCheckBox box : checkBox) {
                                if (!box.isSelected()) {
                                    box.setEnabled(false);
                                }
                            }
                        } else {
                            // 未达到最大选择数量，启用所有复选框
                            for (JCheckBox box : checkBox) {
                                box.setEnabled(true);
                            }
                        }
                    }
                };
                for (int i = 0; i < userIds.size(); i++) {
                    checkBox[i] = new JCheckBox(userIds.get(i));
                    int finalI = i;
                    checkBox[i].setSelected(Arrays.asList(selectedPlayerName)
                            .stream()
                            .anyMatch(item -> userIds.get(finalI).equals(String.valueOf(item))));
                    checkBox[i].addActionListener(checkBoxListener);
                    panel.add(checkBox[i]);
                }
                int result = JOptionPane.showConfirmDialog(
                        this, panel,
                        config.getMinPlayers() == config.getMaxPlayers() ?
                                "请选择邀请"+(config.getMaxPlayers() - 1)+"个玩家" :
                                config.getMinPlayers() - 1 == 0 ? "最多选择邀请" + (config.getMaxPlayers() - 1)+"玩家": "至少选择邀请"+(config.getMinPlayers() - 1)+"个，最多选择邀请"+
                                        (config.getMaxPlayers() - 1)+"玩家"
                        ,
                        JOptionPane.OK_CANCEL_OPTION,
                        JOptionPane.QUESTION_MESSAGE);
                String[] selectedPlayer = Arrays.asList(checkBox).stream().filter(JCheckBox::isSelected)
                        .map(JCheckBox::getText).toArray(String[]::new);
                if (selectedPlayer.length < config.getMinPlayers() - 1) {
                    JOptionPane.showMessageDialog(this, "至少选择邀请"+(config.getMinPlayers() - 1)+"个玩家");
                    return;
                }

                if (result == JOptionPane.OK_OPTION) {
                    // 输出用户选择的选项
                    GameClientManager.INSTANCE.inviteJoinGame(gameRoomId, selectedPlayer,
                            config.getId(), config.getTitle());
                }
            }

            if (null != content.playBtn && content.playBtn.contains(point)) {
                if (selectedPlayerName.size() < config.getMinPlayers()) {
                    JOptionPane.showMessageDialog(this,
                            "游戏开始至少需要" + config.getMinPlayers() + "个玩家");
                    return;
                }
                GameClientManager.INSTANCE.startGame(
                        ClientCacheManager.INSTANCE.getUsername(),
                        gameRoomId,
                        config.getId(),
                        selectedPlayerName.size()
                );
            }

        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    public void addPlayer(String inviteUserId) {
        selectedPlayerName.add(inviteUserId);
        content.selectPlayer(config, selectedPlayerName);
        content.repaint();
    }
    public void toHome() {
        this.open();
        this.selectedPlayerName = Arrays.asList();
        content.state = Content.State.SELECT_GAME;
        this.gameRoomId = null;
        content.repaint();
    }
    public void toGameRoom(InviteJoinGameMessage message) {
        this.config = GameManager.GAMES.stream().filter(item -> message.getGameId().equals(item.getId()))
                .findFirst().get();
        this.setTitle("用户：【" + ClientCacheManager.INSTANCE.getUsername() + "】 " +this.config.getTitle() + " - 游戏房间");
        this.selectedPlayerName = Arrays.asList(
                "【" +message.getRoomMasterId() +"】",
                message.getInviteUserId()
        );
        this.gameRoomId = message.getGameRoomId();
        content.selectPlayer(config, selectedPlayerName);
        content.setRoomMasterId(message.getRoomMasterId());
        content.repaint();
    }

    static class Content extends JPanel {

        private static int GAME_ICON_SIZE = 64;
        private static int GAME_ICON_COUNT = 10;
        private static final int STROKE_WIDTH = 2;
        // 水平间距
        private static int SPACING = (WindowUI.WIDTH - GAME_ICON_SIZE * GAME_ICON_COUNT ) / (GAME_ICON_COUNT + 1);

        private State state;
        private  GameConfig config;

        public Content() {
            this.setBackground(Color.BLACK);
            this.state = State.SELECT_GAME;
        }

        private static void forEach(ForEachGameConfigHandler handler) {
            for (int i = 0; i < GameManager.GAMES.size(); i++) {
                int row = i / GAME_ICON_COUNT;
                int col = i % GAME_ICON_COUNT;
                handler.forEach(row, col,
                        new Rectangle(SPACING * (col + 1) + col * GAME_ICON_SIZE,
                        (row + 1) * SPACING + row * GAME_ICON_SIZE,
                                GAME_ICON_SIZE,
                                GAME_ICON_SIZE), GameManager.GAMES.get(i));
            }
        }


        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            switch(this.state) {
                case SELECT_GAME:
                    renderSelectGame(g);
                    break;
                case SELECT_PLAYER:
                    renderSelectPlayer(g);
                    break;
            }
        }

        private  RoundRectangle2D addPlayerBtn;
        private  RoundRectangle2D playBtn;

        public RoundRectangle2D getAddPlayerBtn() {
            return addPlayerBtn;
        }

        public RoundRectangle2D getPlayBtn() {
            return playBtn;
        }

        private void renderSelectPlayer(Graphics g) {
            // 将 Graphics 对象转换为 Graphics2D 对象，以使用更高级的绘图功能
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int arcWidth = 20;
            int arcHeight = 20;

            for (int i = 0; i < selectedPlayerNames.size(); i++) {
                int row = i / GAME_ICON_COUNT;
                int col = i % GAME_ICON_COUNT;
                g.setColor(new Color(0x409EFF));
                RoundRectangle2D roundedRect = new RoundRectangle2D.Double(
                        SPACING * (col + 1) + col * GAME_ICON_SIZE,
                        SPACING * (row + 1) + row * GAME_ICON_SIZE,
                        GAME_ICON_SIZE, GAME_ICON_SIZE, arcWidth, arcHeight);
                g2d.fill(roundedRect);
                g.setColor(Color.WHITE);
                TextUtil.drawAlignCenter(g, roundedRect.getBounds(), selectedPlayerNames.get(i));
            }
            if (selectedPlayerNames.size() < config.getMaxPlayers()) {
                int row = selectedPlayerNames.size() / GAME_ICON_COUNT;
                int col = selectedPlayerNames.size() % GAME_ICON_COUNT;
                g.setColor(new Color(0x409EFF));
                g2d.setStroke(new BasicStroke(2));
                this.addPlayerBtn = new RoundRectangle2D.Double(
                        SPACING * (col + 1) + col * GAME_ICON_SIZE,
                        SPACING * (row + 1) + row * GAME_ICON_SIZE,
                        GAME_ICON_SIZE, GAME_ICON_SIZE, arcWidth, arcHeight);
                g2d.draw(this.addPlayerBtn);
                g.setColor(Color.WHITE);
                TextUtil.drawAlignCenter(g, this.addPlayerBtn.getBounds(), "邀请");
            } else {
                this.addPlayerBtn = null;
            }

            if (this.roomMasterId == ClientCacheManager.INSTANCE.getUsername()) {
                g.setColor(new Color(0x409EFF));
                this.playBtn = new RoundRectangle2D.Double(
                        (WindowUI.WIDTH - 200) / 2,
                        WindowUI.HEIGHT * 0.8,
                        200, 38, 4, 4);
                g2d.fill(this.playBtn);
                g.setColor(Color.WHITE);
                TextUtil.drawAlignCenter(g, this.playBtn.getBounds(), "开始游戏");
            }
        }

        private List<String>  selectedPlayerNames;

        public void selectPlayer(GameConfig config, List<String> selectedPlayerNames) {
            this.config = config;
            this.selectedPlayerNames = selectedPlayerNames;
            this.state = State.SELECT_PLAYER;
        }

        private void renderSelectGame(Graphics g) {
            // 定义圆角矩形的尺寸和圆角半径
            int arcWidth = 20;
            int arcHeight = 20;
            // 将 Graphics 对象转换为 Graphics2D 对象，以使用更高级的绘图功能
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            forEach((row,col, rect, config) -> {
                g.setColor(Color.WHITE);
                g2d.fill(new RoundRectangle2D.Double(rect.getBounds().x,
                        rect.getBounds().y ,
                        rect.getBounds().width ,
                        rect.getBounds().height, arcWidth, arcHeight));
                g.setColor(Color.BLACK);
                TextUtil.drawAlignCenter(g, rect.getBounds(), config.getTitle());
            });
        }

        private String roomMasterId;
        public void setRoomMasterId(String username) {
            this.roomMasterId = username;
        }


        enum State {
            SELECT_GAME,
            SELECT_PLAYER
        }


        interface ForEachGameConfigHandler  {
            void forEach(
                    int row,
                    int col,
                    Rectangle rect,
                    GameConfig gameConfig);
        }
    }
}
